﻿using System;
using System.Collections.Generic;
using System.Data.Services.Common;
using System.Data.SqlTypes;
using System.Runtime.Serialization;

namespace Pottery.Model.Infrastructure.Models
{
    /// <summary>
    /// Order.
    /// </summary>
    [DataContract]
    [DataServiceEntity]
    public class Order : IValidatable, IAssignable, INullable
    {
        #region Constructors
        /// <summary>
        /// Constructor with params. Creates a new Order. 
        /// </summary>
        /// <param name="orderNumber">order Number</param>
        /// <param name="productsInOrder">List of products in order</param>
        /// <param name="customerInOrder">Buyer</param>
        /// <param name="orderType">Order type (Regular, Custom, Mixed)</param>
        /// <param name="orderRegDate">Order registration date</param>
        /// <param name="needDelivery">Need delivery?</param>
        /// <param name="deliveryAddress">Delivery address, if needs delivery</param>
        /// <param name="releaseDate">Date of release</param>
        /// <param name="isPaid">Is it paid?</param>
        /// <param name="totalOrderPrice">Total price amount of order</param>
        /// <param name="status">Status of order</param>
        public Order(int orderNumber, List<Product> productsInOrder, Customer customerInOrder, Enumerators.OrderType orderType,
            DateTime orderRegDate, bool needDelivery, string deliveryAddress, DateTime releaseDate, bool isPaid,
            double totalOrderPrice, Enumerators.OrderStatus status)
        {
            mOrderNumber = orderNumber;
            mProductsInOrder = productsInOrder;
            mCustomerInOrder = customerInOrder;
            mOrderType = orderType;
            mOrderRegDate = orderRegDate;
            mNeedDelivery = needDelivery;
            mDeliveryAddress = deliveryAddress;
            mReleaseDate = releaseDate;
            mIsPaid = isPaid;
            mTotalOrderPrice = totalOrderPrice;
            mStatus = status;

        }

        /// <summary>
        /// Default constructor. Creates an Order with default params.
        /// </summary>
        public Order()
        {
            mCustomerInOrder = new Customer();
            mProductsInOrder = new List<Product>();
        }
        #endregion

        #region Properties
        /// <summary>
        /// Number of Order
        /// </summary>
        [DataMember]
        public int OrderNumber
        {
            get { return mOrderNumber; }
            set
            {
                if (!IsNull)
                    mOrderNumber = value;
            }
        }

        /// <summary>
        /// List of Products in Order
        /// </summary>
        [DataMember]
        public List<Product> ProductsInOrder
        {
            get { return mProductsInOrder; }
            set
            {
                if (!IsNull)
                    mProductsInOrder = value;
            }
        }

        /// <summary>
        /// Customer (buyer)
        /// </summary>
        [DataMember]
        public Customer CustomerInOrder
        {
            get { return mCustomerInOrder; }
            set
            {
                if (!IsNull)
                    mCustomerInOrder = value;
            }
        }

        /// <summary>
        /// Type of order.
        /// (Regular, Custom, Mixed)
        /// </summary>
        [DataMember]
        public Enumerators.OrderType OrderType
        {
            get { return mOrderType; }
            set
            {
                if (!IsNull)
                    mOrderType = value;
            }
        }

        /// <summary>
        /// Order`s registration date.
        /// </summary>
        [DataMember]
        public DateTime OrderRegDate
        {
            get { return mOrderRegDate; }
            set
            {
                if (!IsNull)
                    mOrderRegDate = value;
            }
        }

        /// <summary>
        /// Delivery request.
        /// </summary>
        [DataMember]
        public bool NeedDelivery
        {
            get { return mNeedDelivery; }
            set
            {
                if (!IsNull)
                    mNeedDelivery = value;
            }
        }

        /// <summary>
        /// Delivery Address.
        /// </summary>
        [DataMember]
        public string DeliveryAddr
        {
            get { return mDeliveryAddress; }
            set
            {
                if (!IsNull)
                    if (NeedDelivery)
                    {
                        mDeliveryAddress = value;
                    }
                    else throw new InvalidOperationException("You don`t need delivery...");
            }
        }

        /// <summary>
        /// Date of release of the current order
        /// </summary>
        [DataMember]
        public DateTime ReleaseDate
        {
            get { return mReleaseDate; }
            set
            {
                if (!IsNull)
                    mReleaseDate = value;
            }
        }

        /// <summary>
        /// IsPaid
        /// </summary>
        [DataMember]
        public bool IsPaid
        {
            get { return mIsPaid; }
            set
            {
                if (!IsNull)
                    mIsPaid = value;
            }
        }

        /// <summary>
        /// Total order price
        /// </summary>
        [DataMember]
        public double TotalOrderPrice
        {
            get { return mTotalOrderPrice; }
            set
            {
                if (!IsNull)
                    mTotalOrderPrice = value;
            }
        }

        /// <summary>
        /// Order Status 
        /// (PreOrdered, ConformedWithCustomer, ApprovedByForeman, InProduce, InStock, InDelivery, Finished)
        /// </summary>
        [DataMember]
        public Enumerators.OrderStatus Status
        {
            get { return mStatus; }
            set
            {
                if (!IsNull)
                    mStatus = value;
            }
        }
        #endregion

        #region IValidate implementation
        // <summary>
        /// Checks instance for data`s validity
        /// </summary>
        /// <returns>checking result</returns>
        public bool Validate()
        {
            return true;
        }
        #endregion

        #region IAssignable implementation

        /// <summary>
        /// Copy data from current object to object in param.
        /// </summary>
        /// <param name="obj">object to change </param>
        public void AssignTo(object obj)
        {
            if (IsNull)
                throw new InvalidOperationException();

            if (obj == null)
                throw new ArgumentNullException("obj");

            if (obj is Order)
            {
                Order ord = obj as Order;

                ord.mOrderNumber = mOrderNumber;
                ord.mProductsInOrder = mProductsInOrder;
                ord.mCustomerInOrder = mCustomerInOrder;
                ord.mOrderType = mOrderType;
                ord.mOrderRegDate = mOrderRegDate;
                ord.mNeedDelivery = mNeedDelivery;
                ord.mDeliveryAddress = mDeliveryAddress;
                ord.mReleaseDate = mReleaseDate;
                ord.mIsPaid = mIsPaid;
                ord.mTotalOrderPrice = mTotalOrderPrice;
                ord.mStatus = mStatus;

                ord.mNull = false;

                return;
            }

            throw new NotSupportedException("Not supported type!");
        }

        #endregion

        #region INullable implementation
        public bool IsNull
        {
            get { return mNull; }
        }

        public static Order Null
        {
            get
            {
                Order ord = new Order();
                ord.mNull = true;
                return ord;
            }
        }
        #endregion

        #region private Fields
        private DateTime mReleaseDate = default(DateTime);
        private bool mIsPaid = default(bool);
        private double mTotalOrderPrice = default(double);
        private List<Product> mProductsInOrder;
        private Customer mCustomerInOrder = null;
        private int mOrderNumber = default(int);
        private Enumerators.OrderType mOrderType = Enumerators.OrderType.Regular;
        private DateTime mOrderRegDate = default(DateTime);
        private bool mNeedDelivery = default(bool);
        private string mDeliveryAddress = default(string);
        private Enumerators.OrderStatus mStatus = Enumerators.OrderStatus.PreOrdered;
        private bool mNull = false;
        #endregion



    }
}
